#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>


int main(int argc, char** argv)
{
        // 第 1 步：创建一个套接字
        int sock = socket(AF_INET, SOCK_STREAM, 0);
        /*
        socket 函数的参数解读：
        第一个参数表示地址家族，基本上都是 AF_INET，表示使用英特网地址家族；
        第二个参数表示套接字类型，通常有两种，即 SOCK_STREAM 和 SOCK_DGRAM，前者表示流式套接字，用于基于 TCP 协议的通信，后者表示数据报式套接字，用于基于 UDP 协议的通信；
        第三个参数表示使用的通信协议编号，0 表示使用默认协议。

        socket 函数的返回值为新套接字的描述符，如果失败，返回值为 -1
        */

        if(sock == -1)
        {
                perror("socket");
                return 1;
        }
    
 // 第 3 步：连接服务器
        struct sockaddr_in srv_addr;
        srv_addr.sin_family = AF_INET;                  // 指定地址家族
        srv_addr.sin_addr.s_addr = inet_addr(argv[1]);  // 指定目标服务器的 IP 地址
        srv_addr.sin_port = htons(atoi(argv[2]));       // 指定目标服务器的端口号

        if(-1 == connect(sock, (struct sockaddr*)&srv_addr, sizeof(srv_addr)))
        {
                // 连接服务器失败
                perror("connect");
                return 1;
        }


        // 第 4 步：收发数据
	char data1[100];
	char data2[100] = "你好，我是客户端";
	//接收数据
        int ret1 = recv(sock, data1, sizeof(data1), 0);  // 最后一个参数为 0 表示采用默认的方式接收数据，返回值>为实际成功接收的字节数，小于或等于其第三个参数
        //int ret = read(sock, data, sizeof(data));  // 和 recv 函数等效

	//接收服务器端信息
        if(ret1 == -1)
        {
                perror("recv fail");
        }
        else
        {
                printf("服务器说：%s\n", data1);
        }
	
	//发送信息给服务器端
	int ret2 = send(sock, data2, sizeof(data2), 0);
	
	if(ret1 == -1)
    	{
        	perror("send fail");
    	}

  
    // 第 5 步：断开连接（如果不需要继续和目标服务器端通信的话）
        //close(sock);

        return 0;
}

